# -*- coding: utf-8 -*-
import KBEngine
from KBEDebug import * 
import ConstDef
import IKernel
import ValChangedDef

class FUSE_FIELD(dict):
	"""
	"""
	def __init__(self):
		"""
		"""
		dict.__init__(self)

		self.owner = None
		self.ownSelfKey = None

	def isKeySameType(self, k):
		for selfK, selfV in self.items():
			if k == selfK:
				continue

			if type(k) != type(selfK):
				# 这里必须保证key的类型一致
				assert(False)
				return False
			else:
				return True

		return True

	def __setitem__(self, k, v):
		dataType = type(v)
		if dataType != int \
			and dataType != float \
			and dataType != bool \
			and dataType != str :
			DEBUG_MSG("FUSE_FIELD value only suport int float bool str, dict please use FUSE_FIFELD_NEST")
			assert(False)

		if self.isKeySameType(k) == False:
			return

		oldVal = self.get(k)
		changeType = ValChangedDef.DATA_NONE
		if oldVal == None:
			changeType = ValChangedDef.DATA_ADD
		elif oldVal == v:
			return
		else:
			changeType = ValChangedDef.DATA_UPDATE

		dict.__setitem__(self, k, v)

		changeValDict = {
			k:v
		}

		oldValDict = {
			k:oldVal
		}
		self.notifyChanged(changeType, oldValDict, changeValDict)

	def notifyChanged(self, changeType, oldValDict, changeValDict):
		if self.owner == None:
			return

		from FUSE_FIELD_NEST import FUSE_FIELD_NEST
		if isinstance(self.owner, FUSE_FIELD_NEST):
			oldVal = {self.ownSelfKey:oldValDict}
			changeVal = {self.ownSelfKey:changeValDict}
			self.owner.notifyChanged(changeType, oldVal, changeVal)
		else:
			# 剩下的就是实体，不用判断，如果没有就出错了，可以及时修改
			self.owner.onValChanged(self.ownSelfKey, oldValDict, changeType)

			from logic import ModuleMgr
			handler = ModuleMgr.Instance().getModule("ContainerHandler")
			handler.syncData(self.owner, self.ownSelfKey, changeType, changeValDict)

	def clear(self):
		oldValDict = eval(str(self))
		dict.clear(self)

		changeValDict = None

		from FUSE_FIELD_NEST import FUSE_FIELD_NEST
		if type(self) == FUSE_FIELD:
			changeValDict = FUSE_FIELD()
		elif type(self) == FUSE_FIELD_NEST:
			changeValDict = FUSE_FIELD_NEST()
		else:
			assert(False)
	
		self.notifyChanged(ValChangedDef.DATA_REMOVE, oldValDict, changeValDict)

	def setdefault(self, key, default=None):
		oldVal = self.get(key)
		self.__setitem__(key, default)

		if oldVal == None:
			return default

		return oldVal

	def update(self, other):
		if type(other) != type(self):
			#只支持本类型
			assert(False)
			return

		addOldDict = {}
		addChangedDict = {}

		updateOldDict = {}
		updateChangedDict = {}

		for k, v in other.items():
			oldVal = self.get(k)
			if oldVal == None:
				addOldDict[k] = None
				addChangedDict[k] = v
			else:
				updateOldDict[k] = v
				updateChangedDict[k] = v

		dict.update(self, other)

		if len(addOldDict) > 0:
			self.notifyChanged(ValChangedDef.DATA_ADD, addOldDict, addChangedDict)

		if len(updateOldDict) > 0:
			self.notifyChanged(ValChangedDef.DATA_UPDATE, updateOldDict, updateChangedDict)

	def popitem(self):
		kv = dict.popitem(self)
		oldValDict = {
			kv[0]		: kv[1],
		}
		changeValDict = {
			kv[0] : None,
		}
		self.notifyChanged(ValChangedDef.DATA_REMOVE, oldValDict, changeValDict)
		return kv

	def pop(self, key, default=None):
		oldVal = self.get(key)
		if oldVal == None:
			return default

		val = dict.pop(self, key, default)
		oldValDict = {
			key		: oldVal
		}

		changeValDict = {
			key		: None
		}

		self.notifyChanged(ValChangedDef.DATA_REMOVE, oldValDict, changeValDict)

		return val

	def asDict(self):
		dictData = {}
		dictData["L1"] = []

		from FUSE_FIELD_NEST import FUSE_FIELD_NEST
		if type(self.owner) == FUSE_FIELD_NEST:
			dictData["L1"].append(
				{
					"ktype"			: "STRING",
					"key"			: "FUSE_FIELD_NEST_key",
					"vtype"			: IKernel.Instance().getDataStringType(self.ownSelfKey),
					"val"			: self.ownSelfKey,
				}
			)

		for key, val in self.items():
			fuseField = {
				"ktype"			: IKernel.Instance().getDataStringType(key),
				"key"			: str(key),
				"vtype"			: IKernel.Instance().getDataStringType(val),
				"val"			: str(val),
			}

			dictData["L1"].append(fuseField)

		return dictData

	def createFromDict(self, dictData):
		# dictData["info"] 是一个 FUSE_FIELD 的 list
		for fuseField in dictData["L1"]:
			k = None
			v = None
			strKType = fuseField["ktype"]
			strKey = fuseField["key"]
			if strKType == "STRING" or strKType == "UNICODE":
				k = strKey
			elif strKType == "DOUBLE" or strKType == "FLOAT":
				k = float(strKey)
			else:
				k = int(strKey)

			strVType = fuseField["vtype"]
			strVal = fuseField["val"]
			if strVType == "STRING" or strVType == "UNICODE":
				v = strVal
			elif strVType == "DOUBLE" or strVType == "FLOAT":
				v = float(strVal)
			else:
				v = int(strVal)

			self[k] = v

		return self

class FUSE_FIELD_PICKLER:
	def __init__(self):
		pass

	def createObjFromDict(self, dct):
		return FUSE_FIELD().createFromDict(dct)

	def getDictFromObj(self, obj):
		return obj.asDict()

	def isSameType(self, obj):
		return isinstance(obj, FUSE_FIELD)

inst = FUSE_FIELD_PICKLER()